package com.ruirui.demo;

public class TestStringBufferAndBuilder {

    public static  void testStringBuilder(StringBuilder sb) {
        for (int i = 0; i < 1000; i++) {
            sb.append(Thread.currentThread().getName())
              .append("-")
              .append(i)
              .append(";");
        }
    }

    public static void testStringBuffer(StringBuffer sb) {
        for (int i = 0; i < 1000; i++) {
            sb.append(Thread.currentThread().getName())
              .append("-")
              .append(i)
              .append(";");
        }
    }

    public static void main(String[] args) throws InterruptedException {

        StringBuilder stringBuilder = new StringBuilder();
        StringBuffer  stringBuffer  = new StringBuffer();

        Thread t1 = new Thread(() -> testStringBuilder(stringBuilder), "T1");
        Thread t2 = new Thread(() -> testStringBuilder(stringBuilder), "T2");
        Thread t3 = new Thread(() -> testStringBuffer(stringBuffer),  "T3");
        Thread t4 = new Thread(() -> testStringBuffer(stringBuffer),  "T4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();

        t1.join();   // 保证线程执行完
        t2.join();
        t3.join();
        t4.join();

        System.out.println("StringBuilder长度：" + stringBuilder.length());
        System.out.println("StringBuffer长度："  + stringBuffer.length());

        //为什么？？stringBuilder线程不安全，stringBuffer线程安全
        /**
         * 因为 StringBuilder 不是线程安全 的实现，多个线程同时对它执行 append 时，内部会出现：
         * 覆盖写入：两个线程在同一偏移量写入，导致部分数据被覆盖。
         * 长度更新丢失：i 字段的 ++ 操作不是原子性的，线程 A 刚写完但还没来得及把 i 加 i，线程 B 又把新的数据写到同一位置，于是出现重复或缺失。
         * 扩容冲突：当容量不足触发扩容时，可能多个线程各自创建新的数组，结果旧数组里的数据丢失。
         * 因此，每次运行得到的 StringBuilder 长度和内容都可能不同；而 StringBuffer 由于所有方法都加了 synchronized，长度始终为 2000，内容也完整。
         */
    }
}
